package xdu.lz.stage2_design_pattern.chapter2_single_pattern;

//懒汉加载模式：去获得对象的时候才去试着创建，带来的问题是线程安全
public class Singleton3 {

    private static volatile Singleton3 instance;

    private Object obj1;
    private Object obj2;
    private Singleton3(){
        //init some resource need very long time

        //.....

        obj1 = new Object();
        obj2 = new Object();
    }

    //可能在多线程下导致成员变量的空指针异常。
    //假设有多个线程在等锁，第一个拿到锁的线程在heap上创建了singleInstance实例但是obj1和obj2还没有创建完
    //此时其他线程拿到instance，操作obj1和obj2会空指针。

    //加上volatile可以保证obj1和obj2在创建singleInstance前被创建，保证了顺序
    public static Singleton3 getInstance(){
        if(instance == null){
            synchronized (Singleton3.class){
                if(instance == null){
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                System.out.println(Singleton3.getInstance());
            }).start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis() - time);
    }
}
